﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows.Forms;

namespace Marmat.Forms.Skin
{
    /// <summary>
    /// 步骤条组件
    /// 引导用户按照流程完成任务的分步导航条，可根据实际应用场景设定步骤，步骤不得少于 2 步
    /// </summary>
    public class Steps : ScrollControl
    {
        /// <summary>
        ///  初始化 Marmat.Forms.Skin.Steps 类的新实例。
        /// </summary>
        public Steps()
        {
            SetStyle(ControlStyles.Selectable, true);
            SetStyle(ControlStyles.ResizeRedraw, true); //尺寸变化后绘制
            SetStyle(ControlStyles.Opaque, false); //改善绘图质量
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
            this.BackColor = Color.White;
        }

        /// <summary>
        ///  获取或设置控件的背景色。
        /// </summary>
        [DefaultValue(typeof(Color), nameof(Color.White))]
        public override Color BackColor { get => base.BackColor; set => base.BackColor = value; }

        /// <summary>
        /// 获取或设置一个值，该值指示 System.Windows.Forms.SplitContainer 面板处于水平方向还是垂直方向。
        /// </summary>
        [Category("行为"), Description("获取或设置一个值，该值指示 System.Windows.Forms.SplitContainer 面板处于水平方向还是垂直方向。")]
        [DefaultValue(typeof(System.Windows.Forms.Orientation), nameof(System.Windows.Forms.Orientation.Horizontal))]
        public System.Windows.Forms.Orientation Orientation { get; set; } = System.Windows.Forms.Orientation.Horizontal;

        /// <summary>
        /// 获取或设置当前激活步骤
        /// </summary>
        [DefaultValue(0)]
        [Category("行为"), Description("获取或设置当前激活步骤。")]
        public int Active { get; set; } = 0;


        /// <summary>
        /// 获取或设置当前步骤的状态
        /// </summary>
        [DefaultValue(1)]
        [Category("行为"), Description("获取或设置当前步骤的状态。")]
        public StepsStatusEnum ProcessStatus { get; set; } = StepsStatusEnum.Process;

        /// <summary>
        /// 获取或设置 Steps 组件的步骤集合。
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public List<StepsItem> Items { get; } = new List<StepsItem>();

        /// <summary>
        /// 获取或设置结束步骤的状态
        /// </summary>
        [DefaultValue(2)]
        [Category("行为"), Description("获取或设置结束步骤的状态。")]
        public StepsStatusEnum FinishStatus { get; set; } = StepsStatusEnum.Finish;

        /// <summary>
        /// 引发 System.Windows.Forms.Control.Paint 事件。
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            switch (this.Orientation)
            {
                case Orientation.Horizontal:
                    break;
                case Orientation.Vertical:
                    {
                        int top = 0;
                        for (int i = 0; i < this.Items.Count; i++)
                        {
                            var item = this.Items[i];
                            var itemEventArgs = this.OnMeasureItem(e.Graphics, i);
                            Rectangle rect = new Rectangle(this.Padding.Left, this.Padding.Top + top - this.VerticalScroll.Value, itemEventArgs.ItemWidth, itemEventArgs.ItemHeight);
                            this.OnDrawItem(new DrawItemEventArgs(e.Graphics, this.Font, rect, i, DrawItemState.Default));
                            top += itemEventArgs.ItemHeight;
                        }
                        this.AutoScrollMinSize = new Size(0, top + this.Padding.Bottom);
                    }
                    break;
            }
            base.OnPaint(e);
        }

        /// <summary>
        /// 创建所有者描述的 System.Windows.Forms.ListBox 和确定列表项的大小时发生。
        /// </summary>
        protected virtual MeasureItemEventArgs OnMeasureItem(Graphics graphics, int index)
        {
            MeasureItemEventArgs arg = new MeasureItemEventArgs(graphics, index);
            int interval = 5;
            StepsItem item = this.Items[index];
            var size = graphics.MeasureString(item.Description, new Font("微软雅黑", 9.0f), this.Width - this.Padding.Horizontal - interval * 2);
            arg.ItemHeight = 24 + (int)size.Height + interval * 6;
            arg.ItemWidth = this.Width - this.Padding.Horizontal;
            if (this.MeasureItem != null)
                this.MeasureItem.Invoke(this, arg);
            return arg;
        }

        /// <summary>
        /// 引发 DrawItem 事件。
        /// </summary>
        /// <param name="e"></param>
        protected void OnDrawItem(DrawItemEventArgs e)
        {
            if (this.DrawItem != null)
                this.DrawItem.Invoke(this, e);
            else
            {
                int interval = 5;
                Color color = Color.Gray;
                StepsItem item = this.Items[e.Index];
                switch (item.Status)
                {
                    case StepsStatusEnum.Default:
                        if (this.Active > e.Index)
                            color = Color.Black;
                        else if (this.Active == e.Index)
                            color = Color.FromArgb(64, 158, 255);
                        else if (this.Active < e.Index)
                            color = Color.Silver;
                        break;
                    case StepsStatusEnum.Wait:
                        color = Color.Gray;
                        break;
                    case StepsStatusEnum.Process:
                        color = Color.Black;
                        break;
                    case StepsStatusEnum.Finish:
                        color = Color.FromArgb(64, 158, 255);
                        break;
                    case StepsStatusEnum.Error:
                        color = Color.FromArgb(245, 108, 108);
                        break;
                    case StepsStatusEnum.Success:
                        color = Color.FromArgb(103, 194, 58);
                        break;
                }
                Size icon_size = new Size(24, 24);
                var pen = new Pen(color, 2);
                Rectangle icon_rect = new Rectangle(e.Bounds.X + interval, e.Bounds.Y + interval, icon_size.Width, icon_size.Height);
                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                if (item.Image != null)
                {
                    var icon = item.Image.CutEllipse();
                    e.Graphics.DrawImage(icon, icon_rect, new Rectangle(0, 0, icon.Width, icon.Height), GraphicsUnit.Pixel);
                }
                else
                {
                    e.Graphics.DrawEllipse(pen, icon_rect);
                    TextRenderer.DrawText(e.Graphics, (e.Index + 1).ToString(), new Font("微软雅黑", 9.0f), icon_rect, color, Color.Transparent, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.NoPadding);
                }
                if (this.Items.Count - 1 > e.Index)
                {
                    e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
                    Rectangle vertical_rect = new Rectangle(icon_rect.X, icon_rect.Bottom + 2, icon_rect.Width, e.Bounds.Height - icon_rect.Height - 2);
                    pen = new Pen(Color.FromArgb(192, 196, 204), 2);
                    e.Graphics.DrawLine(pen, vertical_rect.X + (vertical_rect.Width) / 2, vertical_rect.Top, vertical_rect.X + (vertical_rect.Width) / 2, vertical_rect.Bottom);
                }

                Rectangle title_rect = new Rectangle(icon_rect.Right + interval, e.Bounds.Y + interval, e.Bounds.Width - icon_rect.Width - interval * 2 - 1, icon_size.Height);
                TextRenderer.DrawText(e.Graphics, item.Title, new Font("微软雅黑", 12.0f), title_rect, color, Color.Transparent, TextFormatFlags.Left | TextFormatFlags.VerticalCenter | TextFormatFlags.NoPadding);

                Rectangle description_rect = new Rectangle(icon_rect.Right + interval, icon_rect.Bottom + interval, e.Bounds.Width - icon_rect.Width - interval * 2 - 1, e.Bounds.Height - icon_size.Height - interval);
                using (Brush brush = new SolidBrush(color))
                {
                    StringFormat sf = new StringFormat();
                    sf.FormatFlags = StringFormatFlags.NoClip;
                    e.Graphics.DrawString(item.Description, new Font("微软雅黑", 9.0f), brush, description_rect, sf);
                }
                //e.Graphics.DrawRectangle(Pens.Red, icon_rect);
                //e.Graphics.DrawRectangle(Pens.Green, title_rect);
                //e.Graphics.DrawRectangle(Pens.Black, description_rect);
            }
        }


        /// <summary>
        /// 创建所有者描述的 System.Windows.Forms.ListBox 和确定列表项的大小时发生。
        /// </summary>
        public event MeasureItemEventHandler MeasureItem;

        /// <summary>
        /// 在所有者绘制的 System.Windows.Forms.ListBox 在视觉外观更改时发生。
        /// </summary>
        public event DrawItemEventHandler DrawItem;
    }
}
